#
# This file is part of the kernelstudio package.
#
# (c) 2014-2025 zlin <admin@kernelstudio.com>
#
# For the full copyright and license information, please view the LICENSE file
# that was distributed with this source code.
import logging
import time
from queue import Queue, Empty
from threading import Thread

from ksai.context import Application
from ksai.document.extractor.factory import extractor_factory
from ksai.models.document_attachment import DocumentContext, DocumentStatus

logger = logging.getLogger(__name__)


class DocumentExtractorProcessor:
    _contexts = Queue()
    _stop_event = False
    _app: Application = None
    _worker_thread: Thread = None

    def __init__(self):
        super().__init__()

    def _runner(self):
        while not self._stop_event or not self._contexts.empty():
            try:
                # 设置超时时间避免永久阻塞，方便退出
                context = self._contexts.get(timeout=5)
                if self._process(context):
                    self._contexts.task_done()
            except Empty:
                # 队列为空时继续等待
                continue
            except Exception as e:
                logger.error("Exception raised while processing document: %s", str(e))
                time.sleep(1)

    def _process(self, context: DocumentContext):
        try:
            if context.document.status != DocumentStatus.EXTRACTING.name:
                context.document.status = DocumentStatus.EXTRACTING.name

                # 文档提取
                documents = extractor_factory.extract(context.attachment)

                if documents:
                    context.document.status = DocumentStatus.EXTRACTED.name
                    return True
        except Exception as e:
            logger.error(f"Processing error for document {context.document.uuid}: {str(e)}", exc_info=True)
        return False

    def start(self, app: Application):
        if not self._app:
            self._app = app
        # 确保只启动一个工作线程
        if not self._worker_thread or not self._worker_thread.is_alive():
            self._stop_event = False
            self._worker_thread = Thread(target=self._runner)
            self._worker_thread.daemon = True
            self._worker_thread.start()
            logger.info("Document extractor processor started")
        else:
            logger.info("Processor is already running")

    def stop(self):
        """停止处理器"""
        self._stop_event = True
        logger.info("Waiting for document processor to stop...")
        if self._worker_thread and self._worker_thread.is_alive():
            self._worker_thread.join(timeout=30)
        logger.info("Document extractor processor stopped")

    def put(self, context: DocumentContext):
        self._contexts.put(context)
        return self


extractor_processor = DocumentExtractorProcessor()
